package com.jhj.utils;

import java.math.BigDecimal;

public class MathBigDecimalUtil {
	// 默认除法运算精度
	private static final int DEF_DIV_SCALE = 2;

	/**
	 * 汉语中数字大写
	 */
	private static final String[] CN_UPPER_NUMBER = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
	/**
	 * 汉语中货币单位大写，这样的设计类似于占位符
	 */
	private static final String[] CN_UPPER_MONETRAY_UNIT = { "分", "角", "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾",
			"佰", "仟", "兆", "拾", "佰", "仟" };
	/**
	 * 特殊字符：整
	 */
	private static final String CN_FULL = "整";
	/**
	 * 特殊字符：负
	 */
	private static final String CN_NEGATIVE = "负";
	/**
	 * 金额的精度，默认值为2
	 */
	private static final int MONEY_PRECISION = 2;
	/**
	 * 特殊字符：零元整
	 */
	private static final String CN_ZEOR_FULL = "零元" + CN_FULL;

	// 这个类不能实例化
	private MathBigDecimalUtil() {
	}

	/**
	 * 提供精确的加法运算。
	 * 
	 * @param v1
	 *            被加数
	 * @param v2
	 *            加数
	 * @return 两个参数的和
	 */
	public static BigDecimal add(BigDecimal b1, BigDecimal b2) {
		return b1.add(b2);
	}

	/**
	 * 提供精确的减法运算。
	 * 
	 * @param v1
	 *            被减数
	 * @param v2
	 *            减数
	 * @return 两个参数的差
	 */
	public static BigDecimal sub(BigDecimal b1, BigDecimal b2) {
		return b1.subtract(b2);
	}

	/**
	 * 提供精确的乘法运算。
	 * 
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @return 两个参数的积
	 */
	public static BigDecimal mul(BigDecimal b1, BigDecimal b2) {
		return b1.multiply(b2);
	}

	/**
	 * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后10位，以后的数字四舍五入。
	 * 
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @return 两个参数的商
	 */
	public static BigDecimal div(BigDecimal b1, BigDecimal b2) {
		return div(b1, b2, DEF_DIV_SCALE);
	}

	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
	 * 
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的商
	 */
	public static BigDecimal div(BigDecimal b1, BigDecimal b2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，直接取整
	 * 
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @return 两个参数的商
	 */
	public static BigDecimal divForRoundIng(BigDecimal b1, BigDecimal b2) {
		return b1.divide(b2, 0, BigDecimal.ROUND_DOWN);
	}

	/**
	 * 提供精确的小数位四舍五入处理。
	 * 
	 * @param b
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return 四舍五入后的结果
	 */
	public static BigDecimal round(BigDecimal b, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 使用BigDecimal，保留小数点后两位
	 */
	public static String round2(BigDecimal bd) {

		bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
		return bd.toString();
	}

	public static BigDecimal saveTwoDigital(BigDecimal bd) {

		bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
		return bd;
	}

	/*
	 * 判断 bigdecimal 参数 是否 为 合适的 价钱 值--> 即必须为 正数，可以为小数
	 */
	public static boolean decideIsMoneyNum(BigDecimal moneyNum) {

		double d = moneyNum.doubleValue();

		if (d < 0) {
			System.out.println("小数");
			System.out.println(d);
			return false;
		}
		System.out.println(d);
		return true;
	}

	/**
	 * 计算数值平均值，并且判断小数点，放入区间 0， 0.5 ， 1 1. = 0 ， 则不变 2 > 0 && < 0.5 , 则为0.5 3. > 0.5
	 * , 则为1
	 * 
	 * @param args
	 */
	public static double getValueStepHalf(double s, int size) {

		double r = s;
		double f = s / size;
		BigDecimal bg = new BigDecimal(f);
		double f1 = bg.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();

		int decimal = (int) f1;
		double fractional = f1 - decimal;

		if (fractional > 0 && fractional <= 0.5) {
			f = decimal + 0.5;
		} else if (fractional > 0.5) {
			f = decimal + 1;
		}

		return f;
	}

	/**
	 * 把输入的金额转换为汉语中人民币的大写
	 * 
	 * @param numberOfMoney
	 *            输入的金额
	 * @return 对应的汉语大写
	 */
	public static String number2CNMontrayUnit(BigDecimal numberOfMoney) {
		StringBuffer sb = new StringBuffer();
		// -1, 0, or 1 as the value of this BigDecimal is negative, zero, or
		// positive.
		int signum = numberOfMoney.signum();
		// 零元整的情况
		if (signum == 0) {
			return CN_ZEOR_FULL;
		}
		// 这里会进行金额的四舍五入
		long number = numberOfMoney.movePointRight(MONEY_PRECISION).setScale(0, 4).abs().longValue();
		// 得到小数点后两位值
		long scale = number % 100;
		int numUnit = 0;
		int numIndex = 0;
		boolean getZero = false;
		// 判断最后两位数，一共有四中情况：00 = 0, 01 = 1, 10, 11
		if (!(scale > 0)) {
			numIndex = 2;
			number = number / 100;
			getZero = true;
		}
		if ((scale > 0) && (!(scale % 10 > 0))) {
			numIndex = 1;
			number = number / 10;
			getZero = true;
		}
		int zeroSize = 0;
		while (true) {
			if (number <= 0) {
				break;
			}
			// 每次获取到最后一个数
			numUnit = (int) (number % 10);
			if (numUnit > 0) {
				if ((numIndex == 9) && (zeroSize >= 3)) {
					sb.insert(0, CN_UPPER_MONETRAY_UNIT[6]);
				}
				if ((numIndex == 13) && (zeroSize >= 3)) {
					sb.insert(0, CN_UPPER_MONETRAY_UNIT[10]);
				}
				sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
				sb.insert(0, CN_UPPER_NUMBER[numUnit]);
				getZero = false;
				zeroSize = 0;
			} else {
				++zeroSize;
				if (!(getZero)) {
					sb.insert(0, CN_UPPER_NUMBER[numUnit]);
				}
				if (numIndex == 2) {
					if (number > 0) {
						sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
					}
				} else if (((numIndex - 2) % 4 == 0) && (number % 1000 > 0)) {
					sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
				}
				getZero = true;
			}
			// 让number每次都去掉最后一个数
			number = number / 10;
			++numIndex;
		}
		// 如果signum == -1，则说明输入的数字为负数，就在最前面追加特殊字符：负
		if (signum == -1) {
			sb.insert(0, CN_NEGATIVE);
		}
		// 输入的数字小数点后两位为"00"的情况，则要在最后追加特殊字符：整
		if (!(scale > 0)) {
			sb.append(CN_FULL);
		}
		return sb.toString();
	}

	public static void main(String[] args) {
		// BigDecimal pay = new BigDecimal(0.01);
		// System.out.println("pay = " + pay.toString());
		// BigDecimal pay_round_2 = MathBigDeciamlUtil.round(pay, 2);
		// System.out.println("pay保留两位小数 = " + pay_round_2.toString());
		// BigDecimal p1 = new BigDecimal(100);
		// BigDecimal p2 = MathBigDeciamlUtil.mul(pay, p1);
		// BigDecimal p3 = MathBigDeciamlUtil.round(p2, 0);
		// System.out.println("pay乘以100 = " + p3.toString());

		// decideIsMoneyNum(new BigDecimal(00002.1));
		double serviceHour = 8.0;
		serviceHour = MathBigDecimalUtil.getValueStepHalf(serviceHour, 3);

		System.out.println(serviceHour);

		double totalServiceHour = 11.56;
		System.out.println(Math.rint(totalServiceHour));
		
		double money = 2020004;
        BigDecimal numberOfMoney = new BigDecimal(money);
        String s = MathBigDecimalUtil.number2CNMontrayUnit(numberOfMoney);
        System.out.println("你输入的金额为：【"+ money +"】   #--# [" +s.toString()+"]");
	}
}
